import os
import time
import re
import versionFile as vf
from shutil import copy
import subprocess as sp
import sys
class CCmTool(object):
    '''the CM tool'''
    def __init__(self):
        self.logFile = None

    def EditConfigSpec(self):
        pass

    def SetLogFile(self, logFile):
        self.logFile = logFile

    def Update(self, path):
        pass

    def CheckOut(self, path):
        pass

    def CheckIn(self, path):
        pass

    def Add(self, path):
        pass

    def ApplyLabel(self, label, path):
        pass

    def UpdateAll(self, path):
        self.Update(path)


class CCmToolCC(CCmTool):
    '''Clear Case'''
    def __init__(self):
        super(CCmToolCC, self).__init__()

    def EditConfigSpec(self,path):
        prePath=os.getcwd()
        os.chdir(path)
        os.system("cleartool edcs")
        os.chdir(prePath)

    def UpdateAll(self, path):
        #for clearcase, before update the whole view we first check config spec
        self.EditConfigSpec(path)

    def UpdateByFile(self, file):
        sp.call("cleartool setcs -force %s" % file, stdout=self.logFile, stderr=self.logFile)

    def Update(self, path):
        sp.call("cleartool update %s" % path, stdout=self.logFile, stderr=self.logFile)

    def CheckOut(self, path):
        #print ("cleartool checkout -nc %s" % path)
        sp.call("cleartool checkout -nc %s" % path, stdout=self.logFile, stderr=self.logFile)

    def CheckIn(self, path):
        #print ("cleartool checkin -nc -ide -pti %s" % path)
        sp.call("cleartool checkin -nc -ide -pti %s" % path, stdout=self.logFile, stderr=self.logFile)

    def ApplyLabel(self, label, path, replace=False):
        if replace:
            cmd = "cleartool mklabel -nc -replace -r %s %s" % (label, path)
        else:
            cmd = "cleartool mklabel -nc -r %s %s" % (label, path)

        sp.call(cmd, stdout=self.logFile, stderr=self.logFile)

    def Add(self, path, base=''):
        #base is an dir which can check out

        print ("cleartool add %s" % path)

        #first checkout a parent dir
        if base=='':
            #no set base dir, we check out the parent dir
            dp = os.path.dirname(path)
        else:
            #base dir is set, we can check out this dir
            dp = base

        self.CheckOut(dp)

        if os.path.exists(path):
            #print ("cleartool mkelem -nc -ci -pti -mkpath %s" % path)
            sp.call("cleartool mkelem -nc -ci -pti -mkpath %s" % path, stdout=self.logFile, stderr=self.logFile)
        else:
            #print ("cleartool mkelem -nc -no -pti %s", path)
            sp.call("cleartool mkelem -nc -nco -pti %s" % path, stdout=self.logFile, stderr=self.logFile)

        self.CheckIn(dp)




class CView(object):
    def __init__(self,home):
        self.home=home
        os.chdir(home)

        #default using ClearCase as CM
        self.cmTool = CCmToolCC()
        self.logFile = None

    def SetCmTool(self, cmTool):
        self.cmTool = cmTool

    def SetLogFile(self, logFile):
        self.logFile = logFile
        self.cmTool.SetLogFile(logFile)

    #get the view home path
    def GetHome(self):
        return self.home

    def Compile(self):
        pass

    def SaveImage(self):
        pass

    def GenerateCode(self):
        pass

    def UpdateVersionFile(self):
        pass

    def UpdateAll(self):
        '''update the whole view'''
        #do update action
        self.cmTool.UpdateAll(self.home)

    def UpdateByFile(self, file):
        self.cmTool.UpdateByFile(file)

class CDcmView(CView):
    '''View for NISSAN DCM
    It includes 3 VOB:
       GM_VLBS    -------- For S12 code
       NISSAN_DCM -------- For NISSAN document
       Novanto    -------- For Sgold code'''

    DIR_PATH_NOVANTO_CODE = r"Novanto\code"
    DIR_PATH_RHAPSODY_PROJECT = os.path.join(DIR_PATH_NOVANTO_CODE, r"rhapsody\model")
    DIR_PATH_CODE_TARGET = os.path.join(DIR_PATH_RHAPSODY_PROJECT, r"Svt\Target")
    DIR_PATH_SGOLD_BUILD_IMAGE = os.path.join(DIR_PATH_NOVANTO_CODE, r"native\casnad_system\system-build\HW\MPE")
    PATH_PROJECT = os.path.join(DIR_PATH_RHAPSODY_PROJECT, "Svt.rpy")

    DIR_PATH_NISSAN_DCM = r"Nissan_DCM"


    def __init__(self,home):
        super(CDcmView, self).__init__(home)
        #self.DIR_PATH_NOVANTO_CODE = os.path.join(self.home, self.DIR_PATH_NOVANTO_CODE)
        #self.DIR_PATH_RHAPSODY_PROJECT = os.path.join(self.home, self.DIR_PATH_RHAPSODY_PROJECT)
        #self.DIR_PATH_CODE_TARGET = os.path.join(self.home, self.DIR_PATH_CODE_TARGET)
        #self.DIR_PATH_SGOLD_BUILD_IMAGE = os.path.join(self.home, self.DIR_PATH_SGOLD_BUILD_IMAGE)
        #self.PATH_PROJECT = os.path.join(self.home, self.PATH_PROJECT)

    def SetConfig(self, config):
        self.config = config


    def ChangeBuildScript(self):
        prePath = os.getcwd()
        os.chdir(self.DIR_PATH_NOVANTO_CODE)

        orig_build_file = "build.bat"
        build_script_file = "build_script.bat"

        if os.path.exists(build_script_file):
            os.remove(build_script_file)

        #--------Change build script file
        origBuildFile = file(orig_build_file)
        buildFile = file(build_script_file, 'w+')

        #this loop is used to find 'goto ERROR' line
        #the clean_script.bat file should not include the content before 'goto ERROR' line
        lines = origBuildFile.readlines()
        ix=lines.index("goto ERROR\n")

        del lines[0:ix+1]

        lines.insert(0, "if %1=='INFINITI' goto BUILD_NOVANTO_NISSAN_INFINITI_DCM\n")
        lines.insert(0, "if %1=='L42L' goto BUILD_NOVANTO_NISSAN_DFL_DCM\n")
        lines.insert(0, "if %1=='DFL' goto BUILD_NOVANTO_NISSAN_DFL_DCM\n")
        lines.insert(0, "if %1=='NCIC' goto BUILD_NOVANTO_NISSAN_DFL_DCM\n")
        lines.insert(0, "if %1=='EV' goto BUILD_NOVANTO_NISSAN_EV_DCM\n")
        lines.insert(0, "if %1=='BCR' goto BUILD_NOVANTO_NISSAN_EV_DCM\n")
        lines.insert(0, "if %1=='NONE' goto END\n")

        notepadStr = "IF EXIST builderr.txt (notepad builderr.txt)\n"
        if notepadStr in lines:
            lines.remove(notepadStr)

        for line in lines:
            if re.search("notepad builderr.txt",line):
                lines.remove(line)

        #remove pause statement
        if "pause" in lines:
            lines.remove("pause")
        elif "pause\n" in lines:
            lines.remove("pause\n")

        buildFile.writelines(lines)

        buildFile.close()
        origBuildFile.close()

        os.chdir(prePath)

        return build_script_file


    def ChangeCleanScript(self):
        prePath = os.getcwd()
        os.chdir(self.DIR_PATH_NOVANTO_CODE)

        orig_clean_file = "clean_all.bat"
        clean_script_file = "clean_script.bat"


        #remonve the previous script files
        if os.path.exists(clean_script_file):
            os.remove(clean_script_file)


        #--------Change clean script file
        origCleanFile = file(orig_clean_file)
        cleanFile = file(clean_script_file, 'w+')

        #this loop is used to find 'goto ERROR' line
        #the clean_script.bat file should not include the content before 'goto ERROR' line
        lines = origCleanFile.readlines()
        ix=0
        for line in lines:
            if re.search(":CLEAN_NOVANTO",line) :
                break
            ix = ix+1

        del lines[0:ix]

        #remove pause statement
        if "pause" in lines:
            lines.remove("pause")
        elif "pause\n" in lines:
            lines.remove("pause\n")


        cleanFile.writelines(lines)

        cleanFile.close()
        origCleanFile.close()

        os.chdir(prePath)

        return clean_script_file



    def CompileSgold(self):

        buildFile = self.ChangeBuildScript()
        cleanFile = self.ChangeCleanScript()

        prePath = os.getcwd()
        os.chdir(self.DIR_PATH_NOVANTO_CODE)
        #os.system("%s" % cleanFile)
        #os.system("%s '%s'" % (buildFile, self.config.type))
        sp.call("%s" % cleanFile, stdout=self.logFile, stderr=self.logFile)
        sp.call("%s '%s'" % (buildFile, self.config.type), stdout=self.logFile, stderr=self.logFile)

        os.chdir(prePath)

    def GetReleaseDir(self):
        if self.config.type == "NCIC":
            dcmType = "DFL"
        else:
            dcmType = self.config.type

        if self.config.sgold_ver_high != '' and self.config.sgold_ver_low != '' and self.config.sgold_ver_type != '':
            dcmVersion = "{high}.{low}{type}".format(high=self.config.sgold_ver_high, low=self.config.sgold_ver_low, type=self.config.sgold_ver_type)
        else:
            dcmVersion = "00.00D"

        if self.config.saveImageLocation != "NONE":
            #the save location has been set, use it 
            baseDirName = self.config.saveImageLocation
        else:
            if self.config.type == "INFINITI":
                DIR_PATH_RELEASE = os.path.join(self.DIR_PATH_NISSAN_DCM, r"Infiniti_DCM\releases")
            else:
                DIR_PATH_RELEASE = os.path.join(self.DIR_PATH_NISSAN_DCM, r"release")

            baseDirName = "NISSAN_{type}_DCM_{version}".format(type=dcmType, version=dcmVersion)

            baseDirName = os.path.join(DIR_PATH_RELEASE, baseDirName)

        t = time.strftime('%Y%m%d')

        subDirName = "NISSAN_{dtype}_DCM_{version}_{date}".format(dtype=dcmType, version=dcmVersion, date=t)

        return os.path.join(baseDirName, subDirName)


    def MoveSgoldImage(self):
        buildDir = self.DIR_PATH_SGOLD_BUILD_IMAGE

        #get it from version information, if save image location has been set, we would use it later
        relDir = self.GetReleaseDir()


        imgDir = os.path.join(relDir, r"build\sgold")
        if os.path.exists(imgDir) != True:
            os.makedirs(imgDir)

        copy(os.path.join(buildDir, "builderr.txt"), os.path.join(imgDir, "builderr.txt"))
        copy(os.path.join(buildDir, "CAS_NAD2.axf"), os.path.join(imgDir, os.path.basename(relDir)+".axf"))
        copy(os.path.join(buildDir, "CAS_NAD2.eep"), os.path.join(imgDir, os.path.basename(relDir)+".eep"))
        copy(os.path.join(buildDir, "CAS_NAD2.fls"), os.path.join(imgDir, os.path.basename(relDir)+".fls"))
        copy(os.path.join(buildDir, "CAS_NAD2.map"), os.path.join(imgDir, "CAS_NAD2.map"))
        copy(os.path.join(buildDir, "CAS_NAD2.txt"), os.path.join(imgDir, "CAS_NAD2.txt"))
        copy(os.path.join(buildDir, r"CAS_NAD2\BOOT_VECT"), os.path.join(imgDir, "BOOT_VECT"))
        copy(os.path.join(buildDir, r"CAS_NAD2\CAS_NAD2.hex"), os.path.join(imgDir, os.path.basename(relDir)+".hex"))
        copy(os.path.join(buildDir, r"CAS_NAD2\EE_STATIC"), os.path.join(imgDir, "EE_STATIC"))
        copy(os.path.join(buildDir, r"CAS_NAD2\EE_STATIC_proc"), os.path.join(imgDir, "EE_STATIC_proc"))

        print r'copy from "%s" to "%s"' % (os.path.join(buildDir, "builderr.txt"), os.path.join(imgDir, "builderr.txt"))
        print r'copy from "%s" to "%s"' % (os.path.join(buildDir, "CAS_NAD2.axf"), os.path.join(imgDir, os.path.basename(relDir)+".axf"))
        print r'copy from "%s" to "%s"' % (os.path.join(buildDir, "CAS_NAD2.eep"), os.path.join(imgDir, os.path.basename(relDir)+".eep"))
        print r'copy from "%s" to "%s"' % (os.path.join(buildDir, "CAS_NAD2.fls"), os.path.join(imgDir, os.path.basename(relDir)+".fls"))
        print r'copy from "%s" to "%s"' % (os.path.join(buildDir, "CAS_NAD2.map"), os.path.join(imgDir, "CAS_NAD2.map"))
        print r'copy from "%s" to "%s"' % (os.path.join(buildDir, "CAS_NAD2.txt"), os.path.join(imgDir, "CAS_NAD2.txt"))
        print r'copy from "%s" to "%s"' % (os.path.join(buildDir, r"CAS_NAD2\BOOT_VECT"), os.path.join(imgDir, "BOOT_VECT"))
        print r'copy from "%s" to "%s"' % (os.path.join(buildDir, r"CAS_NAD2\CAS_NAD2.hex"), os.path.join(imgDir, os.path.basename(relDir)+".hex"))
        print r'copy from "%s" to "%s"' % (os.path.join(buildDir, r"CAS_NAD2\EE_STATIC"), os.path.join(imgDir, "EE_STATIC"))
        print r'copy from "%s" to "%s"' % (os.path.join(buildDir, r"CAS_NAD2\EE_STATIC_proc"), os.path.join(imgDir, "EE_STATIC_proc"))

    def Compile(self):
        self.CompileSgold()

    def SaveImage(self):
        self.MoveSgoldImage()

    def UpdateSgoldVersionFile(self):
        sgoldVf = vf.CVfSgold(os.path.join(self.DIR_PATH_NOVANTO_CODE, r"native\system\version\code"))
        self.cmTool.CheckOut(sgoldVf.GetFileName())
        sgoldVf.SetConfig(self.config)
        sgoldVf.Change()
        self.cmTool.CheckIn(sgoldVf.GetFileName())

    def UpdateS12VersionFile(self):
        s12Vf = self.GetS12Vf(self.config.type)
        self.cmTool.CheckOut(s12Vf.GetFileName())
        s12Vf.SetConfig(self.config)
        s12Vf.Change()
        self.cmTool.CheckIn(s12Vf.GetFileName())

    def GetS12Vf(self, dcmType):
        if dcmType == "INFINITI":
            s12Vf = vf.CVfS12Infiniti(os.path.join(self.home,r"GM_VLBS\code\src\exec"))
        elif dcmType == "EV":
            s12Vf = vf.CVfS12EV(os.path.join(self.home,r"GM_VLBS\code\src\exec"))
        elif dcmType == "BCR":
            s12Vf = vf.CVfS12EvBcr(os.path.join(self.home,r"GM_VLBS\code\src\exec"))
        elif dcmType == "DFL":
            s12Vf = vf.CVfS12DFL(os.path.join(self.home,r"GM_VLBS\code\src\exec"))
        elif dcmType == "NCIC":
            s12Vf = vf.CVfS12NCIC(os.path.join(self.home,r"GM_VLBS\code\src\exec"))
        elif dcmType == "L42L":
            s12Vf = vf.CVfS12L42L(os.path.join(self.home,r"GM_VLBS\code\src\exec"))
        else:
            s12Vf = vf.CVfS12(os.path.join(self.home,r"GM_VLBS\code\src\exec"), dcmType)

        s12Vf.SetMarket(self.config.market)
        return s12Vf


    def UpdateVersionFile(self):
        sgoldVf = vf.CVfSgold(os.path.join(self.DIR_PATH_NOVANTO_CODE, r"native\system\version\code"))
        s12Vf = vf.CVfS12(os.path.join(self.home,r"GM_VLBS\code\src\exec"), self.config.type)

        #checkout the file
        self.cmTool.CheckOut(sgoldVf.GetFileName())
        self.cmTool.CheckOut(s12Vf.GetFileName())


        #set config to update the version
        s12Vf.SetConfig(self.config)
        sgoldVf.SetConfig(self.config)

        #change file
        sgoldVf.Change()
        s12Vf.Change()

        #checkin the file
        self.cmTool.CheckIn(sgoldVf.GetFileName())
        self.cmTool.CheckIn(s12Vf.GetFileName())

    def GenerateCode(self):
        '''In NISSAN DCM the Sgold code is generated by rhapsody'''

        projName = self.PATH_PROJECT

        #delete all files genereate before
        targetDir = self.DIR_PATH_CODE_TARGET
        if os.path.exists(targetDir):
            for item in os.listdir(targetDir):
                os.remove(os.path.join(targetDir, item))

        #generate code
        #os.system(r"RhapsodyCL -cmd=open %s -cmd=generate" % projName)
        #sp.call(r"RhapsodyCL -cmd=open %s -cmd=generate" % projName, stdout=self.logFile, stderr=self.logFile)
        #the RhapsodyCL command has problem when generate code for derived class

        fName="temp.log"
        sp.call(r"Rhapsody -cmd=setlog %s -cmd=open %s -cmd=generate -cmd=exit" % (fName,projName))
        f=open(fName)
        data = f.read()
        self.logFile.write(data)
        f.close()
        os.remove(fName)

    def BackUpCode(self):
        '''As DCM sgold code is generate, we should back up the generated code'''
        bakDir = self.DIR_PATH_CODE_TARGET + "_Bak"
        tgtDir = self.DIR_PATH_CODE_TARGET

        fList = os.listdir(tgtDir)

        for f in fList:
            #get the file path in back dir
            fp = os.path.join(bakDir, f)

            if os.path.exists(fp):
                #back dir has this file, should check out, update, check in
                print r"Info:->> back up file <%s>" % fp

                self.cmTool.CheckOut(fp)

                time.sleep(1)

                #copy from target dir
                copy(os.path.join(tgtDir,f), fp)


                self.cmTool.CheckIn(fp)
            else:
                #no this file, should add into source control

                #copy from target dir
                copy(os.path.join(tgtDir,f), fp)

                time.sleep(1)
                print r"Info:->> no file (%s), add it" % fp
                self.cmTool.Add(fp)

            #sleep 1s then do it, as clearcase has problem to continuously operation
            time.sleep(2)

    def ApplyLabel(self, replace=False):
        home = self.home
        for vob, label in self.config.label.items():
            p = os.path.join(home, vob)
            self.cmTool.ApplyLabel(label, p, replace)




